/*MODULES USED*/
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>

#include "mise_en_palette.h"
#include "ResChaineCond.h"
#include "../utils/utils.h"
#include "../interface/partage_simu.h"
#include "../interface/messqueue.h"
#include "../interface/variablesglobales.h"
#include "../interface/constantes.h"
#include "../interface/mutexpartage.h"


static mqd_t bal_impr;
static mqd_t bal_erreurs;
static mqd_t bal_messages;
static mqd_t bal_palettes;

static int nb_cart_pal[2]; // nombre de cartons restant à placer sur la palette
static int nb_pal[2]; // nombre de palettes restant à faire

static unsigned short continuer = 1;

/*PROTOTYPES OF LOCAL FUNCTIONS*/
/**
 Initialisation de la tache de mise en palette
*/
void init_mise_en_palette() {
		// for debugging purpose only
	printf("[MiseEnPalette] Coucou la mise en palette! \n");

	init_globaux_pal();
	bal_impr = ouvrir_mqueue(BAL_IMPRESSION_NAME, O_RDONLY);
	bal_erreurs = ouvrir_mqueue(BAL_ERREURS_NAME, O_WRONLY);
	bal_messages = ouvrir_mqueue(BAL_MESSAGES_NAME, O_WRONLY);
	bal_palettes = ouvrir_mqueue(BAL_PALETTES_NAME, O_WRONLY);
}
/**
 Destruction des ressources
*/
void detruire_mise_en_palette() {
	mq_close(bal_impr);
	mq_close(bal_erreurs);
	mq_close(bal_messages);
	mq_close(bal_palettes);
}
/*EXPORTED FUNCTIONS*/
void init_nb_cart_pal() {
	nb_cart_pal[NUM_A] = g_nb_cart_pal_a;
	nb_cart_pal[NUM_B] = g_nb_cart_pal_b;
}

void init_globaux_pal() {
	init_nb_cart_pal();
	nb_pal[NUM_A] = g_nb_pal_a;
	nb_pal[NUM_B] = g_nb_pal_b;
}

void* mise_en_palette(void* parameter) {
	// non utilisé
	(void) parameter;

	init_mise_en_palette();

	while(continuer) {
		struct message msg_recu;

		int taille_lue = lire_message(bal_impr, &msg_recu);
		if (taille_lue == -1) {
			perror("[MiseEnPalette] Echec lire_message");
			exit(1);
		}

		if(msg_recu.type == ARRET) {
			// debug
			printf("[MiseEnPalette] Arrêt complet\n");
			struct message msg_pal_fin;
			msg_pal_fin.type = ARRET;

			mq_send (bal_palettes, (char *)&msg_pal_fin, sizeof(struct message), 1);
			break;
		}

		int type_piece = msg_recu.params[2];

		while(g_shm->palette == NOK) {
			printf("[MiseEnPalette] Debug: pas de palette!\n");
			struct message msg_err;
			msg_err.type = ERRPALETTE;

			mq_send (bal_erreurs, (char *)&msg_err, sizeof(struct message), 1);
			// attendre sur le mutex pour repartir.
			sem_wait(&sem_palette_absente);
			
		}

		nb_cart_pal[type_piece]--;


		printf("[MiseEnPalette] Carton empaletté, restant: %d \n", nb_cart_pal[type_piece]);

		if(nb_cart_pal[type_piece] == 0) {

			while(g_shm->film == NOK) {
				struct message msg_err;
				msg_err.type = ERREMBAL;

				mq_send (bal_erreurs, (char *)&msg_err, sizeof(struct message), 1);
				// attendre sur le mutex pour repartir.
				sem_wait(&sem_err_embal);
			}

			struct message msg_pal;
			msg_pal.type = STOCKER;
			msg_pal.params[0] = msg_recu.params[0];
			msg_pal.params[1] = msg_recu.params[2];
			msg_pal.params[2] = ((type_piece == NUM_A) ? g_nb_pal_a  : g_nb_pal_b) - nb_pal[type_piece];

			mq_send (bal_palettes, (char *)&msg_pal, sizeof(struct message), 1);
			mq_send (bal_messages, (char *)&msg_pal, sizeof(struct message), 1);

			printf("[MiseEnPalette] Nb cart pal = 0, Msg envoyé \n");

			nb_pal[type_piece]--;
			init_nb_cart_pal();

			if(nb_pal[type_piece] == 0) {
				struct message msg_fin;
				msg_fin.type = FINLOT;
				msg_fin.params[0] = msg_recu.params[0];
				msg_fin.params[1] = msg_recu.params[2];
				printf("[MiseEnPalette] Nb pal = 0, envoi msg fin \n");

				mq_send (bal_messages, (char *)&msg_fin, sizeof(struct message), 1);
			}
		}
	}
	detruire_mise_en_palette();
	return 0;
}

void vider_bal_impression() {
	vider_bal(bal_impr);
}
